const { bill, product } = require("../models/bill");
const Joi = require("joi");
const validationMiddleware = require("../middleware/validate");
const response = require("../utils/response");
const router = require("koa-router")();
const XLSX = require("xlsx");
const {
  handleDatabaseError,
  dealNotEmpty,
  dealNotEmptyArry,
  buildRangeQuery,
  paginate,
} = require("../utils/dberrordeal");
const dayjs = require("dayjs");
const { easyCopy } = require("../utils/utils");
const { supplier } = require("../models/supplier");
const rulesSchema = {
  "/addBill": Joi.object({
    product: Joi.array() // 数组
      .items(
        Joi.object({
          pid: Joi.string().required(),
          number: Joi.number().required(),
          price: dealNotEmptyArry("产品价格")
        }) // 每个对象的验证规则
      ) // 数组的验证规则
      .required(), // 数组是必需的,
    invoice: dealNotEmpty("开票情况"),
    amount: Joi.number().min(1).required().messages({
      "number.base": "货款总额必须是数字",
      "number.min": "货款总额必须大于0",
      "any.required": "货款总额是必需的",
    }), isStart: Joi.boolean().required().messages({
      "boolean.base": "是否开始必须是布尔值",
      "any.required": "是否开始是必需的",
    }),
    rate: Joi.number().min(0).max(100).required().messages({
      "number.base": "税率必须是数字",
      "number.min": "税率必须在0到100之间",
      "number.max": "税率必须在0到100之间",
      "any.required": "税率是必需的",
    }),
    PaymentMethodD: Joi.number().min(1).required().messages({
      "number.base": "月结天数必须是数字",
      "number.min": "月结天数必须大于0",
      "any.required": "月结天数是必需的",
    }),
    name: dealNotEmpty("客户名称"),
    // phone: dealNotEmpty("联系方式"),
    DeliveryAddress: dealNotEmpty("送货地址"),
  }),

  "/addProduct": Joi.object({
    name: dealNotEmpty("产品名称"),
    price: dealNotEmptyArry("产品价格"),
    unit: dealNotEmpty("产品单位"),
  }),
  "/putProduct": Joi.object({
    name: dealNotEmpty("产品名称"),
    price: dealNotEmptyArry("产品价格"),
    unit: dealNotEmpty("产品单位"),
  }),
  "/delProduct": Joi.object({
    id: dealNotEmpty("产品id"),
  }),
  "/delBill": Joi.object({
    id: dealNotEmpty("账单id"),
  }),
  "/findSupplier": Joi.object({
    id: dealNotEmpty("账单id"),
  }),
  "/putBill": Joi.object({
    id: dealNotEmpty("账单id"),
    product: Joi.array() // 数组
      .items(
        Joi.object({
          pid: Joi.string().required(),
          number: Joi.number().required(),
          price: dealNotEmptyArry("产品价格")
        }) // 每个对象的验证规则
      ) // 数组的验证规则
      .required(), // 数组是必需的,
    invoice: dealNotEmpty("开票情况"),
    amount: Joi.number().min(1).required().messages({
      "number.base": "货款总额必须是数字",
      "number.min": "货款总额必须大于0",
      "any.required": "货款总额是必需的",
    }),
    isStart: Joi.boolean().required().messages({
      "boolean.base": "是否开始必须是布尔值",
      "any.required": "是否开始是必需的",
    }),
    rate: Joi.number().min(0).max(100).required().messages({
      "number.base": "税率必须是数字",
      "number.min": "税率必须在0到100之间",
      "number.max": "税率必须在0到100之间",
      "any.required": "税率是必需的",
    }),
    name: dealNotEmpty("客户名称"),
    // phone: dealNotEmpty("联系方式"),
    PaymentMethodD: Joi.number().min(1).required().messages({
      "number.base": "月结天数必须是数字",
      "number.min": "月结天数必须大于0",
      "any.required": "月结天数是必需的",
    }),
    DeliveryAddress: dealNotEmpty("送货地址"),
  }),
  "/getBill": Joi.object({
    id: dealNotEmpty("账单id"),
  }),
};
const dealkeyword = (message) => {
  const keywordsWithLogic = {
    已完结: {
      check: () => message.includes("已完结"),
      action: () => 1
    },
  };

  // 改用 for...of 循环替代 forEach
  for (const complexKeyword of Object.keys(keywordsWithLogic)) {
    const { check, action } = keywordsWithLogic[complexKeyword];
    if (check()) {
      return action(); // 这里会直接返回父函数
    }
  }
  return 0; // 全部不匹配时返回0
};
async function getTotalAmount(desc) {
  return new Promise(async (resolve, reject) => {

    const aggregationPipeline = [
      {
        $group: {
          _id: null, // 不进行分组，直接汇总
          totalAmount: { $sum: `$amount` },// 统计金额总值
          totalPreAmount: { $sum: `$preamount` }
        }
      }
    ];

    const result = await bill.aggregate(aggregationPipeline)
    if (result.length > 0) {

      resolve({ totalAmount: result[0].totalAmount.toFixed(2), totalPreAmount: result[0].totalPreAmount.toFixed(2) })

    } else {
      reject()
      console.log('No bills found.');
    }
  })
}
router.post("/getBillList", async (ctx, next) => {
  let data = ctx.request.body;
  let params = ctx.request.query;
  // 动态构建查询条件
  let query = {};
  query.checkTime = data.ShippingDatea
    ? buildRangeQuery(data.ShippingDatea[0], data.ShippingDatea[1], "time")
    : undefined;
  query.ShippingDate = data.ShippingDateb
    ? buildRangeQuery(data.ShippingDateb[0], data.ShippingDateb[1], "time")
    : undefined;
  query.ShippingEDate = data.ShippingDatec
    ? buildRangeQuery(data.ShippingDatec[0], data.ShippingDatec[1], "time")
    : undefined;
  if (data.product)
    query.product = {
      $elemMatch: {
        pid: data.product,
      }, // 精准匹配产品名称
    };
  if (data.name) query.name = { $regex: data.name, $options: "i" }; // 模糊查询客户名称
  if (data.code) query.code = { $regex: data.code, $options: "i" }; // 模糊查询物料
  query.amount = buildRangeQuery(+data.hkminAmount, +data.hkmaxAmount);
  query.PaymentMethodP = buildRangeQuery(+data.yfminAmount, +data.yfmaxAmount);
  query.padid = buildRangeQuery(+data.yf1minAmount, +data.yf1maxAmount);
  query.arrearage = buildRangeQuery(+data.wfminAmount, +data.wfmaxAmount);
  query.isStart = data.isStart
  if (!data.wfminAmount && !data.wfmaxAmount) {
    if ([true, false].includes(data.isPayOff)) {
      query.arrearage = data.isPayOff ? 0 : { $gt: 0 }
    }
  }

  // isPayOff
  // 移除未定义的查询条件
  Object.keys(query).forEach(
    (key) => query[key] === undefined && delete query[key]
  );


  try {
    let bills = await paginate(bill, query, params, ['product.pid'],{ createTime: -1 });
    response.success(ctx, {
      data: {
        list: bills.results,
        total: bills.total,
      },
    });
  } catch (err) {
    handleDatabaseError(ctx, err);
  }
});

router.post("/findSupplier", async (ctx, next) => {
  let data = ctx.request.body;
  await supplier.find({ supplierOrigin: data.id }).then((res) => {
    response.success(ctx, { data: res });
  });
});

router.post('/getTotalAmount', async (ctx, next) => {
  let data = ctx.request.body;
  let params = ctx.request.query;
  // 动态构建查询条件
  let query = {};
  query.checkTime = data.ShippingDatea
    ? buildRangeQuery(data.ShippingDatea[0], data.ShippingDatea[1], "time")
    : undefined;
  query.ShippingDate = data.ShippingDateb
    ? buildRangeQuery(data.ShippingDateb[0], data.ShippingDateb[1], "time")
    : undefined;
  query.ShippingEDate = data.ShippingDatec
    ? buildRangeQuery(data.ShippingDatec[0], data.ShippingDatec[1], "time")
    : undefined;
  if (data.product)
    query.product = {
      $elemMatch: {
        pid: data.product,
      }, // 精准匹配产品名称
    };
  if (data.name) query.name = { $regex: data.name, $options: "i" }; // 模糊查询客户名称
  if (data.code) query.code = { $regex: data.code, $options: "i" }; // 模糊查询物料
  query.amount = buildRangeQuery(+data.hkminAmount, +data.hkmaxAmount);
  query.PaymentMethodP = buildRangeQuery(+data.yfminAmount, +data.yfmaxAmount);
  query.padid = buildRangeQuery(+data.yf1minAmount, +data.yf1maxAmount);
  query.arrearage = buildRangeQuery(+data.wfminAmount, +data.wfmaxAmount);
  if (!data.wfminAmount && !data.wfmaxAmount) {
    if ([true, false].includes(data.isPayOff)) {
      query.arrearage = data.isPayOff ? 0 : { $gt: 0 }
    }
  }
  query.isStart = data.isStart
  // 移除未定义的查询条件
  Object.keys(query).forEach(
    (key) => query[key] === undefined && delete query[key]
  );


  try {
    params.isAll = true
    let bills = await paginate(bill, query, params, ['product.pid']);
    response.success(ctx, {
      data: {
        totalPreAmount: bills.results.reduce((acc, bill) => acc + (bill.preamount || 0), 0).toFixed(2),
        totalAmount: bills.results.reduce((acc, bill) => acc + (bill.amount || 0), 0).toFixed(2)
      },
    });
  } catch (err) {
    handleDatabaseError(ctx, err);
  }
})

router.post("/getProductList", async (ctx, next) => {
  let data = ctx.request.body;
  if (data.isAll) {
    await product
      .find()
      .then((res) => {
        response.success(ctx, { data: res });
      })
      .catch((err) => {
        handleDatabaseError(ctx, err);
      });
    return;
  }
  let params = ctx.request.query;
  let query = {};
  if (data.name) query.name = { $regex: data.name, $options: "i" }; // 模糊查询客户名称
  if (data.desc) query.desc = { $regex: data.desc, $options: "i" }; // 模糊查询客户名称
  Object.keys(query).forEach(
    (key) => query[key] === undefined && delete query[key]
  );

  try {
    let dbfres = await paginate(product, query, params, []);
    response.success(ctx, {
      data: {
        list: dbfres.results,
        total: dbfres.total,
      },
    });
  } catch (err) {
    handleDatabaseError(ctx, err);
  }
});

router.post("/getBill", async (ctx, next) => {
  let data = ctx.request.body;
  await bill.findOne({ _id: data.id }).then((res) => {
    response.success(ctx, { data: res });
  });
});
//根据对账日期和月结天数 计算应该结算的时间 判断如果当前时间戳超过应该结算的时间则返回失

const calculateBillTime = (checkTime, PaymentMethodD, invoice) => {

  //判断如果当前时间戳超过应该结算的时间则返回失
  const time = dayjs(checkTime).add(PaymentMethodD, "day").valueOf()
  if (Date.now() >= time || dealkeyword(invoice) == 1) {
    return 1
  }
  return time
}
async function getProductsByIds(Ids) {
  return new Promise(async (resolve, reject) => {
    try {
      const fproducts = await product.find({ _id: { $in: Ids } });
      if (fproducts.length === 0) {
        resolve([]);
      } else {
        resolve(fproducts);
      }
    } catch (err) {
      reject(err);
    }
  });

}
router.post(
  "/addBill",
  validationMiddleware(rulesSchema),
  async (ctx, next) => {
    let data = ctx.request.body;
    data.createTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
    if (data.product.length !== 0) {
      const pidsWithQuantity = data.product.map(e => ({
        pid: e.pid,
        number: e.number,
        price: e.price[0]
      }));
      if (pidsWithQuantity.length === 0) {
        return response.error(ctx, { message: '产品信息不完整' });
      }
      let fdata = easyCopy(data);
      fdata.product = pidsWithQuantity;
      let tres = calculateBillTime(data.checkTime, data.PaymentMethodD, fdata.invoice)
      fdata.overDate = tres
      await bill
        .create(fdata)
        .then(() => {
          response.success(ctx, {});
        })
        .catch((err) => {
          console.log(err);
          response.error(ctx, {});
        });
    }
  }
);

router.post(
  "/putBill",
  validationMiddleware(rulesSchema),
  async (ctx, next) => {
    let data = ctx.request.body;
    if (data.product.length !== 0) {
      const pidsWithQuantity = data.product.map(e => ({
        pid: e.pid,
        number: e.number,
        price: e.price[0]
      }));
      if (pidsWithQuantity.length === 0) {
        return response.error(ctx, { message: '产品信息不完整' });
      }
      let fdata = easyCopy(data);
      fdata.product = pidsWithQuantity;
      let tres = calculateBillTime(data.checkTime, data.PaymentMethodD, fdata.invoice)
      fdata.createTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
      fdata.overDate = tres
      await bill
        .findOneAndUpdate({ _id: fdata.id }, { $set: fdata })
        .then(() => {
          response.success(ctx, {});
        })
        .catch((err) => {
          response.error(ctx, {});
        });
    }
  }
);

router.post(
  "/delBill",
  validationMiddleware(rulesSchema),
  async (ctx, next) => {
    let data = ctx.request.body;
    await bill.findByIdAndDelete(data.id).then(() => {
      response.success(ctx, {});
    });
  }
);
router.post(
  "/addProduct",
  validationMiddleware(rulesSchema),
  async (ctx, next) => {
    let data = ctx.request.body;
    await product
      .create(data)
      .then(() => {
        response.success(ctx, {});
      })
      .catch((err) => {
        handleDatabaseError(ctx, err, "产品名称已存在");
      });
  }
);

router.post("/getProduct", async (ctx, next) => {
  let id = ctx.request.body.id;
  await product
    .findOne({
      _id: id,
    })
    .then((res) => {
      response.success(ctx, { data: res });
    })
    .catch((err) => {
      handleDatabaseError(ctx, err);
    });
});
router.post("/delProduct", async (ctx, next) => {
  let id = ctx.request.body.id;

  await product
    .findOneAndDelete({ _id: id })
    .then(() => {
      response.success(ctx, {});
    })
    .catch((err) => {
      handleDatabaseError(ctx, err);
    });
});

router.post(
  "/putProduct",
  validationMiddleware(rulesSchema),
  async (ctx, next) => {
    let data = ctx.request.body;
    await product
      .findOneAndUpdate({ _id: data.id }, { $set: data })
      .then(() => {
        response.success(ctx, {});
      })
      .catch((err) => {
        console.log(err);
        handleDatabaseError(ctx, err, "产品名称已存在");
      });
  }
);
router.get("/getRandomCode", async (ctx, next) => {
  let code;
  let isUnique = false;
  while (!isUnique) {
    code =
      "KF" +
      dayjs().format("YYYYMMDD") +
      "-" + dayjs().format("HHmmss")

    await bill.findOne({ code: code }).then((res) => {
      if (!res) {
        isUnique = true;
      }
    });
  }

  response.success(ctx, { data: code });
});

router.post("/exportData", async (ctx, next) => {
  let data = ctx.request.body;
  let params = ctx.request.query;
  // 动态构建查询条件
  let query = {};
  query.checkTime = data.ShippingDatea
    ? buildRangeQuery(data.ShippingDatea[0], data.ShippingDatea[1], "time")
    : undefined;
  query.ShippingDate = data.ShippingDateb
    ? buildRangeQuery(data.ShippingDateb[0], data.ShippingDateb[1], "time")
    : undefined;
  // query.ShippingEDate = data.ShippingDatec
  //     ? buildRangeQuery(data.ShippingDatec[0], data.ShippingDatec[1], "time")
  //     : undefined;
  if (data.product)
    query.product = {
      $elemMatch: {
        pid: data.product,
      }, // 精准匹配产品名称
    };
  if (data.name) query.name = { $regex: data.name, $options: "i" }; // 模糊查询客户名称
  if (data.code) query.code = { $regex: data.code, $options: "i" }; // 模糊查询物料
  query.amount = buildRangeQuery(data.hkminAmount, data.hkmaxAmount);
  query.PaymentMethodP = buildRangeQuery(data.yfminAmount, data.yfmaxAmount);
  query.padid = buildRangeQuery(data.yf1minAmount, data.yf1maxAmount);
  query.arrearage = buildRangeQuery(data.wfminAmount, data.wfmaxAmount);
  if (!data.wfminAmount && !data.wfmaxAmount) {
    if ([true, false].includes(data.isPayOff)) {
      query.arrearage = data.isPayOff ? 0 : { $gt: 0 }
    }
  }
  query.isStart = data.isStart
  params.isAll = true
  // 移除未定义的查询条件
  Object.keys(query).forEach(
    (key) => query[key] === undefined && delete query[key]
  );

  try {

    // 假设这里从数据库获取要导出的数据
    let bills = await paginate(bill, query, params, ["product.pid"]);

    const billData = bills.results.map((item) => ({
      客户名称: item.name,
      联系方式: item.phone,
      创建时间: item.createTime,
      物料编码: item.code,
      产品信息: item.product.map((e, i) => {
        return `产品${i + 1}:名称:${e.pid.name} 数量:${e.number}${e.pid.unit}  单价:￥${e.price && e.price[0]}`;
      }).join(", "),
      对账日期: dayjs(item.checkTime).format("YYYY-MM-DD HH:mm:ss"),
      预付金额: '￥' + Number(item.amount * item.PaymentMethodP / 100).toFixed(2),
      预付率: item.PaymentMethodP + '%',
      税后总额: '￥' + item.amount,
      税率: item.rate + '%',
      税前总额: '￥' + item.preamount,
      已付金额: '￥' + item.padid,
      未付金额: '￥' + item.arrearage,
      是否出货: item.isSend ? '已出货' : '未出货',
      是否启动: item.isSend ? '已启动' : '未启动',
      出货日期: dayjs(item.ShippingDate).format("YYYY-MM-DD"),
      月结天数: item.PaymentMethodD + '天',
      送货地址: item.DeliveryAddress,
      开票情况: item.invoice,
      结算日期: dealkeyword(item.invoice) == 1 ? '已完结' : dayjs(item.overDate).format("YYYY-MM-DD"),
    }));

    // 创建工作簿
    const wb = XLSX.utils.book_new();
    // 创建工作表
    const billWs = XLSX.utils.json_to_sheet(billData);
    // 将工作表添加到工作簿
    XLSX.utils.book_append_sheet(wb, billWs, `账单数据`);
    // 生成 Excel 文件
    const excelBuffer = XLSX.write(wb, { bookType: "xlsx", type: "buffer" });

    // 设置响应头
    ctx.set(
      "Content-Type",
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    );
    ctx.set("Content-Disposition", "attachment; filename=exportData.xlsx");
    // 返回 Excel 文件
    ctx.body = excelBuffer;
  } catch (err) {
    console.log(err, "err");
    handleDatabaseError(ctx, err);
  }
});

module.exports = router;
